package org.spiderflow.logback;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spiderflow.context.SpiderContext;
import org.spiderflow.context.SpiderContextHolder;
import org.spiderflow.core.job.SpiderJobContext;
import org.spiderflow.core.utils.FileUtils;
import org.spiderflow.model.SpiderLog;
import org.spiderflow.model.SpiderWebSocketContext;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class SpiderFlowWebSocketAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
    private static Logger logger = LoggerFactory.getLogger(SpiderFlowWebSocketAppender.class);

    @Override
    protected void append(ILoggingEvent event) {
        SpiderContext context = SpiderContextHolder.get();
        if (context instanceof SpiderWebSocketContext) {
            SpiderWebSocketContext socketContext = (SpiderWebSocketContext) context;
            Object[] argumentArray = event.getArgumentArray();
            List<Object> arguments = getLogs(event, argumentArray);
            socketContext.log(new SpiderLog(event.getLevel().levelStr.toLowerCase(), event.getMessage(), arguments));
        } else if (context instanceof SpiderJobContext) {
            //TODO 日志文件无法显示优化
            SpiderJobContext jobContext = (SpiderJobContext) context;
            List<Object> logs = getLogs(event, event.getArgumentArray());
            String buildLogs = buildLogs(logs);
            OutputStream outputstream = jobContext.getOutputstream();
            try {
                FileUtils.writeBytes(outputstream, buildLogs.getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                logger.error("日志输出异常", e);
            }
        }
    }

    private String buildLogs(List<Object> logs) {
        StringBuilder sb = new StringBuilder();
        for (Object log : logs) {
            sb.append(log);
        }
        return sb.toString();
    }

    private List<Object> getLogs(ILoggingEvent event, Object[] argumentArray) {
        List<Object> arguments = argumentArray == null ? Collections.emptyList() : new ArrayList<>(Arrays.asList(argumentArray));
        ThrowableProxy throwableProxy = (ThrowableProxy) event.getThrowableProxy();
        if (throwableProxy != null) {
            arguments.add(throwableProxy.getThrowable());
        }
        return arguments;
    }
}
